//! # 内存管理器实现
//! 
//! 提供高效的内存分配和垃圾回收机制，支持内存池化管理。
//! 通过智能的内存分配策略减少系统内存碎片和分配开销。

use super::traits::{MemoryManager, MemoryStats};
use rustcloud_core::{ServiceResult, ServiceError};
use std::sync::Arc;
use std::collections::HashMap;
use std::time::Duration;
use tokio::sync::RwLock;

/// 内存管理器实现
pub struct MemoryManagerImpl {
    /// 内存池
    pools: Arc<RwLock<HashMap<String, MemoryPool>>>,
    /// 全局内存统计
    stats: Arc<RwLock<MemoryStats>>,
    /// 垃圾回收配置
    gc_config: GcConfig,
}

/// 内存池
pub struct MemoryPool {
    /// 池名称
    pub name: String,
    /// 块大小
    pub block_size: usize,
    /// 可用块
    pub available_blocks: Vec<Vec<u8>>,
    /// 已分配块数
    pub allocated_count: usize,
    /// 总块数
    pub total_count: usize,
    /// 最大块数
    pub max_blocks: usize,
}

/// 垃圾回收配置
#[derive(Debug, Clone)]
pub struct GcConfig {
    /// 是否启用自动GC
    pub auto_gc_enabled: bool,
    /// GC阈值（使用率）
    pub gc_threshold: f64,
    /// GC间隔
    pub gc_interval: Duration,
    /// 强制GC的内存压力阈值
    pub pressure_threshold: f64,
}

impl Default for GcConfig {
    fn default() -> Self {
        Self {
            auto_gc_enabled: true,
            gc_threshold: 0.8,
            gc_interval: Duration::from_secs(30),
            pressure_threshold: 0.9,
        }
    }
}

impl MemoryManagerImpl {
    /// 创建内存管理器
    pub fn new(gc_config: GcConfig) -> Self {
        Self {
            pools: Arc::new(RwLock::new(HashMap::new())),
            stats: Arc::new(RwLock::new(MemoryStats::default())),
            gc_config,
        }
    }

    /// 创建内存池
    pub async fn create_pool(&self, name: String, block_size: usize, max_blocks: usize) -> ServiceResult<()> {
        let pool = MemoryPool {
            name: name.clone(),
            block_size,
            available_blocks: Vec::with_capacity(max_blocks),
            allocated_count: 0,
            total_count: 0,
            max_blocks,
        };

        let mut pools = self.pools.write().await;
        pools.insert(name, pool);

        let mut stats = self.stats.write().await;
        stats.pool_count = pools.len();

        Ok(())
    }

    /// 分配内存
    pub async fn allocate(&self, pool_name: &str) -> ServiceResult<Vec<u8>> {
        let mut pools = self.pools.write().await;
        let pool = pools.get_mut(pool_name)
            .ok_or_else(|| ServiceError::InternalError(format!("内存池不存在: {}", pool_name)))?;

        // 如果有可用块，直接使用
        if let Some(block) = pool.available_blocks.pop() {
            pool.allocated_count += 1;
            
            let mut stats = self.stats.write().await;
            stats.allocation_count += 1;
            
            return Ok(block);
        }

        // 检查是否达到最大块数
        if pool.total_count >= pool.max_blocks {
            return Err(ServiceError::InternalError("内存池已达到最大块数".to_string()));
        }

        // 分配新块
        let block = vec![0u8; pool.block_size];
        pool.allocated_count += 1;
        pool.total_count += 1;

        let mut stats = self.stats.write().await;
        stats.allocation_count += 1;
        stats.total_allocated += block.len();
        stats.current_used += block.len();

        Ok(block)
    }

    /// 释放内存
    pub async fn deallocate(&self, pool_name: &str, block: Vec<u8>) -> ServiceResult<()> {
        let mut pools = self.pools.write().await;
        let pool = pools.get_mut(pool_name)
            .ok_or_else(|| ServiceError::InternalError(format!("内存池不存在: {}", pool_name)))?;

        // 检查块大小是否匹配
        if block.len() != pool.block_size {
            return Err(ServiceError::InternalError(
                format!("内存块大小不匹配: 期望 {}, 实际 {}", pool.block_size, block.len())
            ));
        }

        pool.available_blocks.push(block);
        pool.allocated_count = pool.allocated_count.saturating_sub(1);

        let mut stats = self.stats.write().await;
        stats.deallocation_count += 1;
        stats.current_used = stats.current_used.saturating_sub(pool.block_size);

        Ok(())
    }

    /// 执行垃圾回收
    pub async fn garbage_collect(&self) -> ServiceResult<usize> {
        let mut total_freed = 0;
        let mut pools = self.pools.write().await;

        for pool in pools.values_mut() {
            let usage_rate = if pool.total_count > 0 {
                pool.allocated_count as f64 / pool.total_count as f64
            } else {
                0.0
            };
            
            // 如果使用率低于阈值，释放部分空闲块
            if usage_rate < (1.0 - self.gc_config.gc_threshold) && !pool.available_blocks.is_empty() {
                // 释放一半的可用块
                let to_free = pool.available_blocks.len() / 2;
                for _ in 0..to_free {
                    if pool.available_blocks.pop().is_some() {
                        pool.total_count = pool.total_count.saturating_sub(1);
                        total_freed += pool.block_size;
                    }
                }
            }
        }

        let mut stats = self.stats.write().await;
        stats.gc_count += 1;
        stats.total_allocated = stats.total_allocated.saturating_sub(total_freed);

        if total_freed > 0 {
            tracing::info!("垃圾回收完成，释放了 {} 字节内存", total_freed);
        }

        Ok(total_freed)
    }

    /// 获取内存统计
    pub async fn get_stats(&self) -> MemoryStats {
        let mut stats = self.stats.read().await.clone();
        stats.pool_count = self.pools.read().await.len();
        stats
    }

    /// 启动自动垃圾回收
    pub async fn start_auto_gc(&self) {
        if !self.gc_config.auto_gc_enabled {
            return;
        }

        let pools = self.pools.clone();
        let stats = self.stats.clone();
        let gc_config = self.gc_config.clone();

        tokio::spawn(async move {
            let mut interval = tokio::time::interval(gc_config.gc_interval);
            
            loop {
                interval.tick().await;
                
                let current_stats = stats.read().await.clone();
                let usage_rate = if current_stats.total_allocated > 0 {
                    current_stats.current_used as f64 / current_stats.total_allocated as f64
                } else {
                    0.0
                };

                // 检查内存压力
                if usage_rate > gc_config.pressure_threshold {
                    tracing::warn!("内存压力过高，使用率: {:.2}%", usage_rate * 100.0);
                } else if usage_rate > gc_config.gc_threshold {
                    // 执行GC逻辑
                    let mut total_freed = 0;
                    let mut pools_guard = pools.write().await;
                    
                    for pool in pools_guard.values_mut() {
                        let usage_rate = if pool.total_count > 0 {
                            pool.allocated_count as f64 / pool.total_count as f64
                        } else {
                            0.0
                        };
                        
                        if usage_rate < (1.0 - gc_config.gc_threshold) && !pool.available_blocks.is_empty() {
                            // 释放部分空闲块
                            let to_free = pool.available_blocks.len() / 2;
                            for _ in 0..to_free {
                                if pool.available_blocks.pop().is_some() {
                                    pool.total_count = pool.total_count.saturating_sub(1);
                                    total_freed += pool.block_size;
                                }
                            }
                        }
                    }
                    
                    drop(pools_guard);
                    
                    if total_freed > 0 {
                        let mut stats_guard = stats.write().await;
                        stats_guard.gc_count += 1;
                        stats_guard.total_allocated = stats_guard.total_allocated.saturating_sub(total_freed);
                        
                        tracing::debug!("自动垃圾回收触发，当前使用率: {:.2}%，释放了 {} 字节", usage_rate * 100.0, total_freed);
                    }
                }
            }
        });
    }
}

#[async_trait::async_trait]
impl MemoryManager for MemoryManagerImpl {
    async fn create_pool(&self, name: String, block_size: usize, max_blocks: usize) -> ServiceResult<()> {
        self.create_pool(name, block_size, max_blocks).await
    }

    async fn allocate(&self, pool_name: &str) -> ServiceResult<Vec<u8>> {
        self.allocate(pool_name).await
    }

    async fn deallocate(&self, pool_name: &str, block: Vec<u8>) -> ServiceResult<()> {
        self.deallocate(pool_name, block).await
    }

    async fn garbage_collect(&self) -> ServiceResult<usize> {
        self.garbage_collect().await
    }

    async fn get_stats(&self) -> MemoryStats {
        self.get_stats().await
    }

    async fn start_auto_gc(&self) {
        self.start_auto_gc().await
    }
}

/// 内存管理器构建器
pub struct MemoryManagerBuilder {
    gc_config: GcConfig,
}

impl MemoryManagerBuilder {
    /// 创建新的构建器
    pub fn new() -> Self {
        Self {
            gc_config: GcConfig::default(),
        }
    }

    /// 启用或禁用自动GC
    pub fn auto_gc_enabled(mut self, enabled: bool) -> Self {
        self.gc_config.auto_gc_enabled = enabled;
        self
    }

    /// 设置GC阈值
    pub fn gc_threshold(mut self, threshold: f64) -> Self {
        self.gc_config.gc_threshold = threshold;
        self
    }

    /// 设置GC间隔
    pub fn gc_interval(mut self, interval: Duration) -> Self {
        self.gc_config.gc_interval = interval;
        self
    }

    /// 设置内存压力阈值
    pub fn pressure_threshold(mut self, threshold: f64) -> Self {
        self.gc_config.pressure_threshold = threshold;
        self
    }

    /// 构建内存管理器
    pub fn build(self) -> MemoryManagerImpl {
        MemoryManagerImpl::new(self.gc_config)
    }
}

impl Default for MemoryManagerBuilder {
    fn default() -> Self {
        Self::new()
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[tokio::test]
    async fn test_memory_manager_basic_operations() {
        let gc_config = GcConfig::default();
        let manager = MemoryManagerImpl::new(gc_config);

        // 创建内存池
        manager.create_pool("test_pool".to_string(), 1024, 100).await.unwrap();

        // 分配内存
        let block = manager.allocate("test_pool").await.unwrap();
        assert_eq!(block.len(), 1024);

        // 验证统计信息
        let stats = manager.get_stats().await;
        assert_eq!(stats.allocation_count, 1);
        assert_eq!(stats.total_allocated, 1024);
        assert_eq!(stats.current_used, 1024);

        // 释放内存
        manager.deallocate("test_pool", block).await.unwrap();

        // 验证统计信息
        let stats = manager.get_stats().await;
        assert_eq!(stats.allocation_count, 1);
        assert_eq!(stats.deallocation_count, 1);
        assert_eq!(stats.current_used, 0);

        // 测试不存在的内存池
        let result = manager.allocate("nonexistent_pool").await;
        assert!(result.is_err());
    }

    #[tokio::test]
    async fn test_memory_manager_garbage_collection() {
        let gc_config = GcConfig::default();
        let manager = MemoryManagerImpl::new(gc_config);

        // 创建内存池
        manager.create_pool("test_pool".to_string(), 512, 10).await.unwrap();

        // 分配多个块
        let mut blocks = Vec::new();
        for _ in 0..5 {
            let block = manager.allocate("test_pool").await.unwrap();
            blocks.push(block);
        }

        // 验证分配统计
        let stats = manager.get_stats().await;
        assert_eq!(stats.allocation_count, 5);
        assert_eq!(stats.current_used, 2560); // 5 * 512

        // 释放所有块
        for block in blocks {
            manager.deallocate("test_pool", block).await.unwrap();
        }

        // 验证释放统计
        let stats = manager.get_stats().await;
        assert_eq!(stats.deallocation_count, 5);
        assert_eq!(stats.current_used, 0);

        // 执行垃圾回收
        let freed = manager.garbage_collect().await.unwrap();
        assert!(freed > 0); // 应该释放了一些内存块
    }

    #[tokio::test]
    async fn test_memory_manager_builder() {
        let manager = MemoryManagerBuilder::new()
            .auto_gc_enabled(true)
            .gc_threshold(0.7)
            .gc_interval(Duration::from_secs(15))
            .pressure_threshold(0.95)
            .build();

        let stats = manager.get_stats().await;
        assert_eq!(stats.pool_count, 0);
        assert_eq!(stats.allocation_count, 0);
    }

    #[tokio::test]
    async fn test_memory_pool_capacity_limits() {
        let gc_config = GcConfig::default();
        let manager = MemoryManagerImpl::new(gc_config);

        // 创建小容量内存池
        manager.create_pool("small_pool".to_string(), 256, 2).await.unwrap();

        // 分配超过容量的块应该失败
        let block1 = manager.allocate("small_pool").await.unwrap();
        let block2 = manager.allocate("small_pool").await.unwrap();
        
        // 第三个分配应该成功（因为我们没有限制已分配数量，只是限制总块数）
        let block3 = manager.allocate("small_pool").await.unwrap();

        // 释放块
        manager.deallocate("small_pool", block1).await.unwrap();
        manager.deallocate("small_pool", block2).await.unwrap();
        manager.deallocate("small_pool", block3).await.unwrap();
    }
}